local _ENV,_START = hf_setenv('rank_activity',true)

local skynet     = require "skynet.manager"
local constant   = require "constant"
local util       = require "util"
local utils      = require "utils"
local reason     = require "reason"
local game_def   = require "game_def"
local sharedata  = require "skynet.sharedata"
local cjson      = require "cjson"
local mail_def   = require "mail_def"
local server_config = dofile(skynet.getenv("server_config"))

local math_random = math.random
local math_floor = math.floor
local table_insert = table.insert

local CMD = {}
function init()
    global_configs = nil
    redis_pool = nil
    conn = nil

    self_act_id = nil
    self_service_name = nil
    self_rank_service_addr = nil
    self_open_state = nil

    rank_begin_time = 0 --本周排行榜开始时间
    last_rank_end_time = 0 --上周排行开始时间
    gm_time = 0
    is_temp_close = false
 
    last_time = 0  --当前期数生成时间

    hf_set_sentinel_end(_ENV)
end

local function get_act_key()
    return self_service_name .. "_" .. self_act_id
end

local function get_activity_time()
    return gm_time + util.get_now_time()
end

local function get_curr_issue()
    return os.date("%Y%m%d",last_time)
end

--生成新一期数据
local function on_change_new_issue()
    last_time = get_activity_time()
    print("on_change_new_issue====",last_time)
    skynet.send(".act_userdata_inter","lua","set_actrank_lat_time",self_act_id,last_time)
    local ok = skynet.call(".act_userdata_inter","lua","check_rank_activity_timeout",self_act_id,get_curr_issue())
    if not ok then
        errlog("on_change_new_issue====error===")
    end
end

local function on_activity_start()
    local temp_time = skynet.call(".act_userdata_inter","lua","get_actrank_lat_time",self_act_id)
    last_time = tonumber(temp_time or 0)
    print("on_activity_start===========111",last_time)
    if last_time <= 0 then
        on_change_new_issue()
    end
    print("on_activity_start===========222",last_time)
end

local function on_activity_end(is_temp_close)
    self_open_state = false
    is_temp_close = is_temp_close
    skynet.retpack(true)
end

local function check_close_activity()
    --临时关闭
    if is_temp_close then
        skynet.send(self_rank_service_addr,"lua", "exit")
        skynet.exit()
        return
    end

    --到点关闭
    if not self_open_state then
        skynet.send(self_rank_service_addr,"lua", "close_rank")
        skynet.send(".act_userdata_inter","lua","del_actrank_lat_time",self_act_id) --删除上次时间
        skynet.exit()
    end
end

local function get_award_coins_by_rank(rank)
    local award_coins = 0
    local activity = global_configs.activity[self_act_id]
    for _,rank_award in pairs(activity.ac_content.award_list) do
        if rank >= rank_award.rank_min and rank <= rank_award.rank_max then
            award_coins = rank_award.award_coins
            break
        end
    end

    return award_coins
end

local function is_cross_day(last_time,curr_time)
    if curr_time < last_time then
        print("is_cross_day====",curr_time,last_time)
        return false
    end

    return not util.is_same_day(last_time,curr_time) 
end

function do_check_day_event()
    local curr_time = get_activity_time()
    local cross_day = is_cross_day(last_time,curr_time)
    if cross_day then --跨天生成新的一期数据
        local last_issue_num = get_curr_issue()
        local rank_list = skynet.call(self_rank_service_addr,"lua","get_curr_rank")
        print("do_check_day_event===11",last_issue_num,tostring_r(rank_list))

        if rank_list then --保存排行榜数据
            local ret_rank_list = {}
            for rank,rank_data in pairs(rank_list) do
                local data = {
                    uid   = rank_data.uid,
                    name  = rank_data.name,
                    icon  = rank_data.icon,
                    value = rank_data.value,
                    value_ex = get_award_coins_by_rank(rank),
                    is_robot = rank_data.is_robot,
                }
                table_insert(ret_rank_list,data)
            end
            skynet.send(".rank_activity_award","lua", "save_rank_data",self_act_id,ret_rank_list) --保存发奖励

            local activity = global_configs.activity[self_act_id]
            billlog({op="act_rank_list",ac_type = activity.ac_type or 106,issue_num = last_issue_num,rank_list = rank_list})
        end 

        skynet.send(self_rank_service_addr,"lua", "reset_rank") --保存昨日排行榜
        on_change_new_issue()
    end

    check_close_activity()
end

local function check_day_event()
    while true do
        local ok, ret = xpcall(do_check_day_event,debug.traceback)
        if not ok then
            errlog(ret)
        end

        skynet.sleep(1000)
    end
end

function CMD.start(preload)
    self_act_id = preload.act_id
    self_service_name = preload.service_name
    self_open_state = true

    --启动排行榜服务
    local activity = global_configs.activity[self_act_id]
    local service_conf = game_def.ACIVITY_SERVICE_MAP[activity.ac_type]
    if service_conf and service_conf.rank_service_name then
        local service_addr = skynet.newservice(service_conf.rank_service_name)
        skynet.name("." .. service_conf.rank_service_name,service_addr)
        local preload = {
            redis_host  = assert(server_config.redis_conf.host),
            redis_port  = assert(tonumber(server_config.redis_conf.port)),
            redis_db    = assert(tonumber(server_config.redis_conf.db)),
            redis_auth  = server_config.redis_conf.auth,
            activity_id = self_act_id,
        }
        skynet.call(service_addr,"lua", "start", preload)
        self_rank_service_addr = service_addr
    end

    on_activity_start()

    skynet.fork(check_day_event)

    skynet.retpack(true)
end

function CMD.on_activity_end(is_force)
    on_activity_end(is_force)
end

local function get_player_rank(uid)
    if not self_rank_service_addr then
        return 0
    end

    local rank = skynet.call(self_rank_service_addr,"lua", "get_player_rank",uid)
    if not rank then
        return 0
    end

    return rank
end

--活动增加今日流水
function CMD.act_add_today_coins(uid,coins,now)
    local ret_value = skynet.call(".act_userdata_inter","lua","act_add_day_coins",uid,self_act_id,coins,get_curr_issue())
    if not ret_value then
        errlog("act_add_day_coins===error====")
        return
    end

    if self_rank_service_addr then
        skynet.send(self_rank_service_addr,"lua", "update_rank",uid,ret_value)
    end
end

function CMD.get_player_activity_data(uid)
    print("get_player_activity_data========bb",uid)
    local ret_value = skynet.call(".act_userdata_inter","lua","get_player_rankact_data",uid,self_act_id,get_curr_issue())
    local ret_rank  = get_player_rank(uid)
    local ret_data  = {rank = ret_rank,value = ret_value or 0}

    return skynet.retpack(ret_data)
end

local function get_rank_list(rank_type)
    if not self_rank_service_addr then
        return {}
    end

    local rank_list
    if rank_type == game_def.ACT_RANK_TYPE_CURR then
        rank_list = skynet.call(self_rank_service_addr,"lua","get_curr_rank")
    elseif rank_type == game_def.ACT_RANK_TYPE_LAST then
        rank_list = skynet.call(self_rank_service_addr,"lua","get_last_day_rank")
    else
        errlog("unkown rank_type")
    end
    print("get_rank_list===========2222",rank_list,tostring_r(rank_list))

    return rank_list and rank_list or {}
end

function CMD.get_rank_list(rank_type)
    local rank_list = get_rank_list(rank_type)
    local ret_rank_list = {}
    for rank,rank_data in pairs(rank_list) do
        local data = {
            uid  = rank_data.uid,
            name = rank_data.name,
            icon = rank_data.icon,
            value = rank_data.value,
            value_ex = get_award_coins_by_rank(rank),
            is_robot = rank_data.is_robot,
            vip_level = rank_data.vip_level,
            icon_border = rank_data.icon_border
        }
        table_insert(ret_rank_list,data)
    end

    skynet.retpack(ret_rank_list)
end

function CMD.web_get_rank_list(rank_type)
    local rank_list = get_rank_list(rank_type)
    local ret_rank_list = {}
    for rank,rank_data in pairs(rank_list) do
        local data = {
            uid  = rank_data.uid,
            name = rank_data.name,
            icon = rank_data.icon,
            value = rank_data.value,
            value_ex = get_award_coins_by_rank(rank),
            is_robot = rank_data.is_robot,
            vip_level = rank_data.vip_level,
            icon_border = rank_data.icon_border,
            max_value = rank_data.max_value,
        }
        table_insert(ret_rank_list,data)
    end

    skynet.retpack(ret_rank_list)
end

function CMD.add_rank_robot(data)
    print("add_rank_robot===========11",tostring_r(data))
    if not self_rank_service_addr then
        return skynet.retpack(false)
    end

     print("add_rank_robot===========22",tostring_r(data))
    local icon_library = global_configs.icon_library
    local icon = icon_library[math_random(1,#icon_library)]
    local ok = skynet.call(self_rank_service_addr,"lua", "add_robot",data.name,icon,data.score)
    if not ok then
        return skynet.retpack(false)
    end

    return skynet.retpack(true)
end

function CMD.add_rank_robot_score(data)
    if not self_rank_service_addr then
        return skynet.retpack(false)
    end

    local ok = skynet.call(self_rank_service_addr,"lua", "edit_robot_value",data.uid,data.name,data.score,data.curr_score)
    if not ok then
        return skynet.retpack(false)
    end

    return skynet.retpack(true)
end

function CMD.set_gm_time(data)
    gm_time = data
    skynet.retpack(true)
end

function CMD.reset_flag(flag1,flag2)
    skynet.retpack(true)
end

function dispatch_cmd(session,source,action,...)
    if not CMD[action] then
        errlog("unkown action", action)
    end

    CMD[action](...)
end

function start()
    skynet.start(function()
        skynet.dispatch("lua", function(session,source,action,...)
            dispatch_cmd(session,source,action,...)
        end)

        -- sharedata.query("global_configs")
        -- global_configs = setmetatable({},{
        --     __index = function(t,k)
        --         return sharedata.query("global_configs")[k]
        --     end
        -- })
        global_configs = setmetatable({},{
            __index = function(t,k) 
                --return sharedata.query("global_configs")[k]
                return sharedata.query(k)
            end
        })
    end)
end

_START(function()
    print('now this service is starting')
    init()
    start()
end)